#include "../card.h"
#include "device.h"
#include "nfc.h"
#include "../card_crypto.h"

/* 调试打印接口 */
#define CARD_LOG(format, ...) OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#define __CARD_LOG(format, ...) __OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)

/* 虚拟硬件接口 */
#define VHW_IRQ_CARD vPIN_I4

/* 读卡事件 */
#define EVENT_READ_CARD (0X00000001)

/* 卡片工作模式 */
static CardMode_enum_t card_mode = CARD_MODE_VERIFY;

__EFRAM static FunctionalState card_func = ENABLE;

/**
  * @brief  处理验证卡片、添加卡片
  * @note   验证卡片是否合法
  *         
  * @param  type：卡片类型
  * @param  pID：卡片ID号
  * @param  len：ID号长度
  * 
  * @return SUCCESS/ERROR
  */
static ErrorStatus Card_ProcessVerifyOrAddCard(uint8_t type, uint8_t *pID, uint8_t len, uint8_t *err)
{
	if (card_mode == CARD_MODE_VERIFY) //验证卡片
	{
		/* 读ID成功：验证卡片是否合法  */
		if (CardCrypto_VerifyCard(pID, len, type, err) != ERROR)
		{
			CARD_LOG("verify success\r\n");
			return SUCCESS;
		}
		CARD_LOG("verify failed\r\n");
	}
	else if (card_mode == CARD_MODE_ADD) //添加卡片
	{
		/* 读ID成功：执行卡片添加流程  */
		if (CardCrypto_AddCard(pID, len, type) != ERROR)
		{
			CARD_LOG("add success\r\n");
			return SUCCESS;
		}
		CARD_LOG("add failed\r\n");
	}
	return ERROR;
}

/**
  * @brief  读取卡片ID 
  * @note   
  *         
  * @param  pID：id缓存区，必须大于10byte
  * @return 无卡返回0，非法卡返回1，正常返回卡号长度（4/7/10）
  */
static uint8_t Card_ReadCardId(uint8_t *pID)
{
	if (card_func == DISABLE) //无刷卡功能
	{
		return 0;
	}
	uint8_t len = 0;
	uint8_t cardType;

	Device_Write(vCAP_SENSE0, NULL, 0, 0);
	Device_Enable(VHW_SPI_CARD);
	pcd_lpcd_end();

	PcdConfig('A');
	len = CardCrypto_ReadCardId(pID, &cardType); //读卡类型和卡ID
	if (len != 0)
	{
		CARD_LOG("Read card id succeed\r\n");
#ifndef CARD_CRYPTO_DISABLE
		uint8_t err = 0;
		if (Card_ProcessVerifyOrAddCard(cardType, pID, len, &err) != SUCCESS) //加密信息验证或者添加卡片
		{
			len |= 0X80;								//非法卡、添加失败：将len的bit7设置为1
			len |= (err == CARD_ERR_NO_ADD) ? 0X40 : 0; //合法卡片但未添加
		}
#endif
	}

	Ws1850s_Init();
	Device_Disable(VHW_SPI_CARD);
	Device_Write(vCAP_SENSE0, NULL, 0, 2);

	return len;
}

/**
  * @brief  读取卡片ID
  *         
  * @note   设计防重复读卡逻辑，将读取到的卡片ID发给订阅者
  */
static uint8_t Card_ReadID(void)
{
	CardMsg_t msg;
	memset((uint8_t *)&msg, 0x00, sizeof(CardMsg_t));
	msg.cardLen = Card_ReadCardId(msg.cardId);
	if (msg.cardLen > 0)
	{
		CARD_LOG("Card len:%#X,  id:%02X %02X %02X %02X\r\n", msg.cardLen, msg.cardId[0], msg.cardId[1], msg.cardId[2], msg.cardId[3]);
		OSAL_MessagePublish(&msg, sizeof(CardMsg_t));
	}
	return msg.cardLen;
}

/**
  * @brief  设置卡片模式
  *
  * @param  mode：模式
  * @return 
  */
static ErrorStatus Card_SetWorkMode(CardMode_enum_t mode)
{
	card_mode = mode;
	return SUCCESS;
}

/**
 * @brief  设置卡片功能开关
 *
 * @param  func：功能
 * @return 
 */
static ErrorStatus Card_SetFunction(FunctionalState status)
{
	card_func = status;
	return SUCCESS;
}

//这个函数是在硬件中断里面跑的，一般在这里创建个ISR事件就行，其他逻辑放到TASK里面的ISR事件去处理
//这个IrqHandle应该要在SLEEP事件里面关掉，在START事件里面开启
//如果休眠后没关闭，后续一但硬件触发中断，就会直接唤醒系统了；正常应该是中断触发，确认读到卡了，才能唤醒
static void Card_IrqHandle(VirtualHardware_enum_t dev, void *data, uint32_t len)
{
	OSAL_EventCreateFromISR(COMP_CARD);
}

//这个函数，是OS里面的空闲TASK掉用的，
//休眠状态下用户触发动作，OS会执行这个handle，确认是否可以唤醒系统
//返回非0表示可以唤醒
static int32_t Card_WakeHandle(uint32_t dev)//所以这个函数里面应该要做读卡的动作，不能创建ISR
{
	// uint8_t cardId[10] = {0};
	// int32_t len = (int32_t)Card_ReadCardId(cardId);
	// return len;
	// return 1;
}


static void Card_Init(void)
{
	static uint8_t init_flag = 0;
	/* 硬件初始化 */
	Device_Enable(VHW_SPI_CARD);
	Ws1850s_Init();
	Device_Disable(VHW_SPI_CARD);

	InputPort_stu_t button_list[] = 
	{
		{"CARD_INT", VHW_IRQ_CARD, INPUT_PORT_LOGIC_LOW, INPUT_PORT_FUNC_SINGLE}, //中断脚
	};
	InputPort_Registered(button_list, OSAL_LENGTH(button_list), Card_IrqHandle);
	InputPort_EnableProt("CARD_INT");	

	// if(!init_flag)
	// {
	// 	init_flag = 1;
	// 	/* 注册中断回调 */
	// 	Device_RegisteredCB(VHW_IRQ_CARD, Card_IrqHandle);
	// }
}

/**
  * @brief  卡片任务函数
  *         
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Card_Task(uint32_t event)
{
	static uint32_t last_time = 0;
	/* 系统启动事件 */
	if (event & EVENT_SYS_START)
	{
		CARD_LOG("Card task start\r\n");
		Card_Init();
		Device_ConfigCB(VHW_IRQ_CARD, ENABLE);	
		// OSAL_EventSingleCreate(COMP_CARD, EVENT_READ_CARD, 50, EVT_PRIORITY_LOW);
		
		SYS_API(Card_SetWorkMode);
		SYS_API(Card_SetFunction);

		return (event ^ EVENT_SYS_START);
	}

	/* 系统休眠事件 */
	if (event & EVENT_SYS_SLEEP)
	{
		Device_ConfigCB(VHW_IRQ_CARD, DISABLE);
		Device_Enable(VHW_SPI_CARD);
		Ws1850s_Init();
		Device_Disable(VHW_SPI_CARD);
		CARD_LOG("Card task sleep\r\n");
		return (event ^ EVENT_SYS_SLEEP);
	}

	/* 系统中断事件 */
	if (event & EVENT_SYS_ISR)
	{
		CARD_LOG("card irq\r\n");
		if ((OSAL_GetTickCount() - last_time > 1000) || (last_time == 0)) //限制触发间隔
		{
			Device_ConfigCB(VHW_IRQ_CARD, DISABLE);
			Card_ReadID();
			Device_ConfigCB(VHW_IRQ_CARD, ENABLE);
			last_time = OSAL_GetTickCount();
		}
		else
		{
			/* 这里需要重新打开lpcd */
			Device_Enable(VHW_SPI_CARD);
			pcd_lpcd_start(DELAT, SWINGSCNT);
			Device_Disable(VHW_SPI_CARD);
		}
		return (event ^ EVENT_SYS_ISR);
	}

	/* 读卡事件 */
	if (event & EVENT_READ_CARD)
	{
		Device_ConfigCB(VHW_IRQ_CARD, DISABLE);
		Card_ReadID();
		Device_ConfigCB(VHW_IRQ_CARD, ENABLE);
		return (event ^ EVENT_READ_CARD);
	}
	return 0;
}
COMPONENT_TASK_EXPORT(COMP_CARD, Card_Task, 16);
COMPONENT_WAKEUP_EXPORT(COMP_CARD, Card_WakeHandle, VHW_IRQ_CARD);
